package scantask.server.utilities.algorithm;

import java.util.Vector;

import scantask.containers.Coordinate;
import scantask.containers.Pest;
import scantask.containers.exceptions.IllegalLocationNameExeption;
import scantask.containers.exceptions.InvalidCoordinateValueException;
import scantask.containers.exceptions.InvalidMeasurementTypeException;
import scantask.containers.exceptions.UnInitializeObjectException;

public class ShepardInterpolation implements InterpolatorInterface {
	//maximal distance between the points
	private final double maxDistance = 3;
	//minimal number of close enough points
	private final double minSamples = 1;
	//dimensions, for now we use only x y
	private final int dimensions = 2;
	//constant for the weights
	private final double pneg = -2;

	public ShepardInterpolation(){}


	private double rad(double[] p1, double[] p2) {
		double sum = 0;
		for (int i=0;i<this.dimensions;i++){
			sum += Math.pow((p1[i]-p2[i]),2);
		}
		return Math.sqrt(sum);
	}


			public static void main(String[] args){
				Vector<Pest> p = new Vector<Pest>();
				try {
					for(int i =0; i<10;i++){
						p.add(new Pest(new Coordinate(i, i), null, i, null, true, "k", "k"));
					}
					System.out.println(new ShepardInterpolation().missingDataInterpolation(p,
							new Pest(new Coordinate(5.5, 5.5), null, -1, null, true, "k", "k")).getValue());
				} catch (UnInitializeObjectException e) {
					
					e.printStackTrace();
				} catch (InvalidMeasurementTypeException e) {
					
					e.printStackTrace();
				} catch (IllegalLocationNameExeption e) {
					
					e.printStackTrace();
				} catch (InvalidCoordinateValueException e) {
					
					e.printStackTrace();
				} catch (InterpolationException e) {
					
					e.printStackTrace();
				}
			}

	@Override
	public Pest missingDataInterpolation(Vector<Pest> data, Pest missingData)
	throws InterpolationException {
		int n = data.size();
		double [][] points = new double[n][this.dimensions];
		double []values = new double[n];
		for(int i = 0; i<n;i++){
			points[i][0] = data.get(i).getCoordinate().getX();
			points[i][1] = data.get(i).getCoordinate().getY();
			values[i] = data.get(i).getValue();
		}
		double[] point = new double[this.dimensions];
		point[0] = missingData.getCoordinate().getX();
		point[1] = missingData.getCoordinate().getY();
		double r, w;
		double sum=0;
		double sumw=0;
		int usedSamples = 0;
		for (int i=0;i<n;i++) {
			if(points[0].length!=this.dimensions) throw new InterpolationException();
			if ((r=rad(point,points[i])) == 0){
				missingData.setValue(values[i]);
				return missingData;
			}
			if(r<this.maxDistance){
				usedSamples++;
				sum += (w = Math.pow(r,this.pneg));
				sumw += w*values[i];
			}
		}
		if(usedSamples<this.minSamples){
			throw new InterpolationException();
		}
		missingData.setValue(sumw/sum);
		return missingData;

	}
}


